//! \file code-sheriff.cpp
// -----------------------------------------------------------------------------
//! This program is free software; you can redistribute it and/or
//! modify it under the terms of the GNU General Public License
//! as published by the Free Software Foundation; either version 2
//! of the License, or (at your option) any later version.
//!
//! This program is distributed in the hope that it will be useful,
//! but WITHOUT ANY WARRANTY; without even the implied warranty of
//! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//! GNU General Public License for more details.
//!
//! You should have received a copy of the GNU General Public License
//! along with this program; if not, write to the Free Software Foundation,
//! Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// -----------------------------------------------------------------------------

// Project
#include "Configuration.h"
#include "CPlugin.h"
#include "CPluginInput.h"

// Standard
#include <Pluma/Pluma.hpp>
#include <iostream>
#include <string>

using namespace std;

// =====[ Local Definitions ]===================================================

// TODO: we will move our program exist status to a header file of it's own
// once we have a more comprehensive list.  For now we will get this list
// kicked off here.  We will also document appropriately after the relocation.
static const int EXIT_STATUS_OKAY = 0; // TODO: I am thinking an error class that can additional log information.


// =====[ Local DataTypes ]=====================================================

// =====[ Local Variables ]=====================================================

// =====[ Local Functions ]=====================================================
static void _CodeSheriff_PrintWelcome(void);
static void _CodeSheriff_LoadPlugins(void);
static void _CodeSheriff_LoadInputPlugins(void);
static void _TrailingSpaces(void);

// =====[ Local Implementation ]================================================


// =============================================================================
//! \brief The start of the main program.
//!
//! This is the main function.  This is where the program starts execution.
//! It is responsible for the high-level organization of the program's
//! functionality, and has access to the command arguments given to the
//! program when it was executed.
//!
//! \param [in] argc
//!   TODO: document
//! \param [in] argv
//!   TODO: document
//!
//! \retval Error
//!   Error code indicating the result of the requested operation.
// -----------------------------------------------------------------------------
int main(int argc, char* argv[])
{
  // TODO: lots of stuff.
  // Determine what the format of the arguments are going to be.
  // Parse the arguments to a (psuedo) configuration database that can be
  // accessed by future code modules... key-pair + instances?

  // Let's start simple, first and only argument will be a source file so we
  // pulse some life through some algorithms.

  // Let's start with whitespace (trailing whitespace & tabs vs. space).

  // TAB_AS_SPACES = Y or N
  // TAB_SPACING = 2


  int Result;                           // Result of requests.
  code_sheriff::CConfiguration* pConfig; // Configuration object.

  // Display some application information.
  _CodeSheriff_PrintWelcome();

  // Get our configuration singleton.
  pConfig = code_sheriff::CConfiguration::getSingleton();

  // Have the configuration parse our command line.
  Result = pConfig->parseCommandLine(argc, argv);
  if (Result != EXIT_STATUS_OKAY)
    { return (Result); }

  // Load the configuration file.
  Result = pConfig->loadConfiguration();
//  if (Result != EXIT_STATUS_OKAY) TODO: restore
//    { return (Result); }




  _CodeSheriff_LoadPlugins();
  _CodeSheriff_LoadInputPlugins();

  // TODO: Temporary tests
  string Value;
//  if (pConfig->getValue("whitespace", Value) == 0)
//    { _TrailingSpaces(); }


  // Exit the application safely.
  return EXIT_STATUS_OKAY;
}


// =============================================================================
//! \brief TODO: document
//!
//! TODO: document
//!
//! \b Example: \code
//! TODO: document
//! \endcode
// -----------------------------------------------------------------------------
static void _CodeSheriff_PrintWelcome(void)
{
  // Display the application message.
  cout << VERSION_MAJOR << "." << VERSION_MINOR << endl;
  cout << endl;
}


// =============================================================================
//! \brief TODO: document
//!
//! TODO: document
//!
//! \b Example: \code
//! TODO: document
//! \endcode
// -----------------------------------------------------------------------------
static void _CodeSheriff_LoadPlugins(void)
{
    pluma::Pluma pluma;

  //  pluma.acceptProviderType<WarriorProvider>();
    pluma.acceptProviderType<code_sheriff::IPluginProvider>();

    // Load libraries
    pluma.loadFromFolder("/home/quandtum/workspace/code-sheriff-build/", true);

    // Get warrior providers into a vector
    std::vector<code_sheriff::IPluginProvider*> providers;
    pluma.getProviders(providers);

    // Create a Warrior from each provider
    std::vector<code_sheriff::IPluginProvider*>::iterator it;
    for (it = providers.begin() ; it != providers.end() ; ++it)
    {
      // Create a warrior
      code_sheriff::IPlugin* pFile = (*it)->create();
      // Display it's description
      std::cout << pFile->getDescription() << std::endl;
      // (...)
      // don't forget to delete it
      delete pFile;
    }

    // TODO: comment
    pluma.unloadAll();
}


// =============================================================================
//! \brief TODO: document
//!
//! TODO: document
//!
//! \b Example: \code
//! TODO: document
//! \endcode
// -----------------------------------------------------------------------------
static void _CodeSheriff_LoadInputPlugins(void)
{
  pluma::Pluma pluma;

  pluma.acceptProviderType<code_sheriff::IPluginInputProvider>();

  // Load libraries
  pluma.loadFromFolder("/home/quandtum/workspace/code-sheriff-build/", true);

  // Get warrior providers into a vector
  std::vector<code_sheriff::IPluginInputProvider*> providers;
  pluma.getProviders(providers);

  // Create a Warrior from each provider
  std::vector<code_sheriff::IPluginInputProvider*>::iterator it;
  for (it = providers.begin() ; it != providers.end() ; ++it)
  {
    // Create a warrior
    code_sheriff::IPluginInput* pFile = (*it)->create();
    // Display it's description
    std::cout << pFile->getDescription() << std::endl;
    // (...)
    // don't forget to delete it
    delete pFile;
  }

  // TODO: comment
  pluma.unloadAll();
}


// =============================================================================
//! \brief TODO: document
//!
//! TODO: document
//!
//! \b Example: \code
//! TODO: document
//! \endcode
// -----------------------------------------------------------------------------
static void _TrailingSpaces(void)
{
  cout << "Checking _TrailingSpaces" << endl;
}
